home *** CD-ROM | disk | FTP | other *** search
- /*
-
- PS PRINT
- A PostScript Downloader written by Nicholas Pavkovic
- © Perimeter, 1987.
- Portions copyrighted by THINK Technologies, Inc., and Apple Computer, Inc.
- No restrictions on non-commercial distribution of program (not source).
-
- PERIMETER
- 1608 North Milwaukee Avenue
- Chicago Illinois 60647
- 312 . 278 . 9509
-
- */
-
- #include <MacTypes.h>
- #include <QuickDraw.h>
- #include <EventMgr.h>
- #include <StdFilePkg.h>
-
- /*
- Libraries linked:
- MacTraps
- sprintf/sscanf
- */
-
- /* FileMgr.h Defs (don’t need whole file) */
-
- #define fnfErr -43
- #define eofErr -39
- extern int FSFCBLen : 0x3F6;
- extern int BootDrive : 0x210;
- extern int SysMap : 0xA58;
-
- /* WindowMgr.h (don’t need whole file) */
-
- #define NewWindow (long) NewWindow
- #define dBoxProc 1
-
- /* General */
-
- #define True 1
- #define False 0
- #define Success 0
- #define Failure -1
- #define Fails == -1
- #define NULL 0L
-
-
- /* Fall-through functions */
-
- #define IssueRead() if( issueread() Fails ) return( Failure )
- #define CheckIfCancelled() if( checkifcancelled() Fails ) return( Failure )
- #define DisplayStatus() if( displaystatus() Fails ) return( Failure )
- #define OpenLChannel() if( openlchannel() Fails ) return( Failure)
- #define PostMessage(x, y ) if( postmessage(x, y) Fails ) return( Failure )
-
- /* PostMessage selectors */
-
- #define FromPrinter 1
- #define FromProgram 0
-
- #define SIMPLEALERT 1000
-
- /* File-related */
-
- int FErr;
- int FileRef;
- SFReply UserReply;
- SFTypeList Fylz;
- Point SFPoint;
- char *OpenName;
- char NullString;
-
- EventRecord theEvent;
- Handle DummyHand1;
- Rect DummyRect;
- long DummyType;
-
- /* Windows */
-
- long PrintWinPtr;
- long DirectWin;
-
- /* Please include InfoWin if you compile and distribute the program */
-
- long InfoWin;
-
- char *InfoString = "A PostScript Downloader written by Nicholas Pavkovic\r\r© Perimeter 1987.\rPortions © THINK and Apple Computer, Inc.\rNon-commercial distribution is permitted.\
- \r\rPERIMETER\r1608 North Milwaukee Avenue\rChicago Illinois 60647\r312 . 278 . 9509\r \
- Developers of LaserLabels™ and QuickScript™\r\r• Click on the mouse to continue.";
-
- /* PAP globals */
-
- typedef struct
- {
- long int systemstuff;
- char statusstr[256];
- } papstatusrec, *papstatusptr;
-
-
- Handle pap;
- long papaddr;
-
- int FlowQuantum;
-
- long unsigned LaserNode;
- int OpenState;
- int WriteState;
- int ReadState;
-
- int ConnectId;
-
- int WriteEof;
- int ReadEof;
-
- char ReadSpace[4096];
- char *WriteBuffer;
-
- int WriteSize;
- int ReadSize;
-
- char *LaserName;
- Handle LaserHand;
- char LaserNameBuff[64];
-
- papstatusrec LaserStatus;
-
- char VirtualPage[4096];
- char MessageBuff[256];
-
- Handle FeedbackHandle;
- long FHandleSize;
-
- long LastStatusDisplay;
-
-
- /*
- SimpleAlert:
- Implements a general alert used for
- most of the terminal error messages.
- */
-
- SimpleAlert( m0 )
- char *m0;
- {
- ParamText( m0, 0L, 0L, 0L );
- NoteAlert( SIMPLEALERT, 0L ) ;
- }
-
- /*
- SFDFilter:
- Filter function for Standard File Dialog.
- Makes the “Open” button context sensitive
- and gives it a heavy outline.
- */
-
- pascal Boolean SFDFilter( dlog, event, itemhit )
- long dlog;
- EventRecord *event;
- int *itemhit;
- {
- if ( event->what == activateEvt && event->modifiers & activeFlag )
- {
- GetDItem( dlog, getOpen, &DummyType, &DummyHand1, &DummyRect );
- SetCTitle( DummyHand1, OpenName );
-
- PenSize(3, 3);
- InsetRect( &DummyRect, -4, -4 );
- FrameRoundRect( &DummyRect, 16, 16);
- PenSize(1,1);
- };
- return( False );
- }
-
- /*
- displaystatus:
- Checks and display status every second,
- even if routine is called more frequently.
- */
-
- displaystatus()
- {
- if( TickCount() - LastStatusDisplay > 60 )
- {
- PapStatus();
- PostMessage( &LaserStatus.statusstr, FromPrinter );
- LastStatusDisplay = TickCount();
- };
- CheckIfCancelled();
- }
-
- /*
- Directions:
- Display text in the directions window.
- */
-
- Directions( text )
- char *text;
- {
- DummyRect.top = 10;
- DummyRect.left = 10;
- DummyRect.right = 342;
- DummyRect.bottom = 80;
-
- SetPort( DirectWin );
- MoveTo( 10, 16 );
- TextBox( &text[1], (long) text[0], &DummyRect, 0 );
- }
-
- main()
- {
- char *source, *dest;
- int counter;
- int sysVRef;
-
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- TEInit();
- InitDialogs(0L);
- FlushEvents(everyEvent, 0);
- InitCursor();
-
- /*
- Read PAP routines into memory.
- OpenResFile uses PMSP; we need only to find boot drive.
- See Tech Note #77 for details.
- */
-
- if( FSFCBLen )
- {
- FErr = GetVRefNum( SysMap, &sysVRef );
- }
- else
- {
- sysVRef = BootDrive;
- };
- SetVol( &NullString, sysVRef );
-
-
-
- FErr = OpenResFile("\pLaserWriter");
-
- if( FErr == -1 )
- {
- SysBeep(1);
- SimpleAlert( "\pThe LaserWriter file could not be found or couldn’t be opened. Returning to Finder.");
- return;
- };
-
- /* Read the PAP code into memory */
-
- if ( ( pap = GetResource( 'PDEF', 10 ) ) == NULL || ResError() )
- {
- SysBeep(1);
- SimpleAlert( "\pThe PAP routines could not be loaded. Returning to Finder.");
- if( FErr != -1 ) CloseResFile( FErr );
- return;
- };
-
- /* Detach PAP */
-
- HLock(pap);
- DetachResource(pap);
- papaddr = (long) *pap;
-
- /* Read printer name from LaserWriter file */
-
- if ( ( LaserHand = GetResource( 'PAPA', -8192 ) ) == NULL || ResError() )
- {
- SysBeep(1);
- SimpleAlert( "\pThe LaserWriter name could not be read. Returning to Finder.");
- return;
- };
-
- /* Create a C string version of the printer name (for messages) and place it into LaserNameBuff */
-
- HLock( LaserHand );
- DetachResource( LaserHand );
- LaserName = *LaserHand;
-
- /*
- Copy the printer name into LaserNameBuff,
- a C string version used for messages to user.
- */
-
- source = (char *) LaserName + 1;
- dest = LaserNameBuff;
- counter = (int) *LaserName;
- while( counter-- ) *dest++ = *source++;
- *dest = 0;
-
- /* Done with LaserWriter file */
-
- CloseResFile( FErr );
-
- /* About PS PRINT... */
-
- DummyRect.left = 62;
- DummyRect.top = 36;
- DummyRect.bottom = 318;
- DummyRect.right = 446;
- InfoWin = NewWindow( 0L, &DummyRect, &NullString, 0xFF, dBoxProc, -1L, False, 0L );
- SetPort( InfoWin );
- TextFace( condense );
- TextFont( 0 );
-
- MoveTo( 10, 36 );
- DrawString( "\pPS PRINT" );
-
- PenPat( gray );
- MoveTo( 64, 26 );
- PenSize( 1, 12 );
- LineTo( 362, 26 );
- PenNormal();
-
- TextFont( 1 );
-
- DummyRect.top = 46;
- DummyRect.left = 10;
- DummyRect.bottom = 282;
- DummyRect.right = 362;
-
- TextBox( InfoString, 314L, &DummyRect, -1 );
-
- while( GetNextEvent( everyEvent, &theEvent) == 0 || theEvent.what != mouseDown ) SystemTask();
-
- DisposeWindow( InfoWin );
-
- /* Setup instruction window. */
-
- DummyRect.left = 80;
- DummyRect.top = 36;
- DummyRect.bottom = 90;
- DummyRect.right = 428;
-
- /*
- Technically, there’s no reason that the directions window should be a dialog,
- but if it’s set up as a normal window, the SFD won’t redisplay the file list
- when a new disk is inserted. Try it. Anyone know why?
- */
-
- DirectWin = (long) NewDialog( 0L, &DummyRect, &NullString, 0xFF, dBoxProc, 0L, 0, 0L, 0L );
-
- SetPort( DirectWin );
- TextFace( condense );
- TextFont( 0 );
-
- FeedbackHandle = NewHandle( 0 );
-
- if( FeedbackHandle == 0 || MemError() )
- {
- SimpleAlert( "\pCan’t Allocate Feedback Handle. Returning to Finder." );
- return;
- };
-
- SFPoint.v = 108;
-
- /* Download loop */
-
- while( 1 )
- {
- SetHandleSize( FeedbackHandle, 0L );
- FHandleSize = 0;
-
- /* Select file to download */
-
- Directions( "\p• Select a file to download, or\r• Click on Cancel to transfer or return to the Finder" );
- SFPoint.h = 80;
- Fylz[0] = 'TEXT';
- OpenName = "\pDownload";
- SFPGetFile( SFPoint, &NullString, 0L, 1, Fylz, 0L, &UserReply, -4000, SFDFilter );
-
- /* If file selected, download it, otherwise transfer */
-
- if ( UserReply.good )
- {
- TextDownload( &UserReply.fName, UserReply.vRefNum );
- }
- else
- {
- Directions( "\p• Select an application to transfer to, or\r• Click on Cancel to return to the Finder" );
- Fylz[0] = 'APPL';
- OpenName = "\pTransfer";
- SFPGetFile( SFPoint, &NullString, (ProcPtr) 0, 1, Fylz, 0L, &UserReply, -4000, SFDFilter);
-
- DisposDialog( DirectWin );
-
- /* If user cancels transfer, return to Finder */
-
- if ( !UserReply.good ) return;
-
- MessageBuff[0] = 0;
- SetVol( &MessageBuff, UserReply.vRefNum );
- Launch( 0, &UserReply.fName );
- };
-
- /* If feedback has been received, save it to a file. */
-
- if( FHandleSize )
- {
- Directions( "\p• Enter a filename to save the printer feedback, or\r• Click on Cancel to continue" );
-
- TryAgain:
-
- SFPoint.h = 104;
- SFPutFile( SFPoint, "\pSave the feedback as:", "\pFeedback", 0L, &UserReply );
-
- /* If user cancels, loop to downloading code */
-
- if ( !UserReply.good ) continue;
-
- FErr = FSOpen( &UserReply.fName, UserReply.vRefNum, &FileRef );
-
- /* If the specified file doesn’t exist, create it */
-
- if( FErr == fnfErr )
- {
- SetVol( &NullString, UserReply.vRefNum);
- FErr = Create( &UserReply.fName, 0, 'EDIT', 'TEXT' );
- FErr = FSOpen( &UserReply.fName, UserReply.vRefNum, &FileRef );
- };
-
- if( FErr != 0 )
- {
- PtoCstr( &UserReply.fName );
- sprintf( &MessageBuff,"The file you requested, “%s”, is not currently available. Error: %d", &UserReply.fName, FErr );
- CtoPstr( &MessageBuff );
- SimpleAlert( &MessageBuff );
- goto TryAgain;
- };
-
- HLock( FeedbackHandle );
- DummyType = FHandleSize;
- SetFPos( FileRef, 1, 0L );
- FSWrite( FileRef, &DummyType, *FeedbackHandle );
- SetEOF( FileRef, DummyType );
- FSClose( FileRef );
- HUnlock( FeedbackHandle );
- };
- };
- }
-
- openlchannel()
- {
-
- long CurrentTime, StartOpening;
-
- Directions("\p• Press \021. (Command-Period) to cancel the download");
-
- /* Set up print window. */
-
- DummyRect.top = 108;
- DummyRect.left = 80;
- DummyRect.bottom = 296;
- DummyRect.right = 428;
-
- PrintWinPtr = NewWindow( 0L, &DummyRect, NullString, 0xFF, dBoxProc, -1L, False, 0L );
- SetPort( PrintWinPtr );
- TextFont( 0 );
- TextFace( condense );
-
- PenSize( 1, 1 );
- PenPat( black );
-
- MoveTo( 10, 24 );
- LineTo( 12, 24 );
- MoveTo( 14, 28 );
- DrawString( "\pProgram" );
- Move( 2, -4 );
- LineTo( 338, 24 );
- LineTo( 338, 86 );
- LineTo( 10, 86 );
- LineTo( 10, 24 );
-
- MoveTo( 10, 108 );
- LineTo( 12, 108 );
- MoveTo( 14, 112 );
- DrawString( "\pPrinter" );
- Move( 2, -4 );
- LineTo( 338, 108 );
- LineTo( 338, 170 );
- LineTo( 10, 170 );
- LineTo( 10, 108 );
-
- TextFont( 1 );
-
- /* Open connection to server */
-
- sprintf( &MessageBuff, "Looking for printer “%s.”", &LaserNameBuff );
- CtoPstr( &MessageBuff );
- PostMessage( &MessageBuff, FromProgram );
-
- FlowQuantum = 8;
- ConnectId = 0;
-
- if ( PapOpen() )
- {
- NoPrinter();
- return( Failure );
- };
-
- sprintf( &MessageBuff, "Establishing connection with “%s.”", &LaserNameBuff );
- CtoPstr( &MessageBuff );
- PostMessage( &MessageBuff, FromPrinter );
-
- StartOpening = TickCount();
-
- while( OpenState > 0 )
- {
- DisplayStatus();
-
- CurrentTime = TickCount();
- if( CurrentTime - StartOpening > 1800 )
- {
- NoPrinter();
- return( Failure );
- };
-
- CheckIfCancelled();
- };
-
- if ( OpenState < 0 )
- {
- NoPrinter();
- return( Failure );
- };
-
- PostMessage( "\pConnection established.", FromProgram );
-
- ReadState = 0;
- WriteState = 0;
- ReadEof = 0;
- WriteEof = 0;
- ReadSize = 0;
- WriteSize = 0;
-
- return( Success );
- }
-
- issueread()
- {
- long oldsize;
- char *fbptr, *readptr;
-
- if ( ReadState <= 0 )
- {
- /* Negative ReadState indicates communications failure */
-
- if ( ReadState < 0 )
- {
- EndPCom();
- return( Failure );
- };
-
- /*
- ReadState == 0 => successful read.
- ReadSize>0 => There’s feedback.
- */
-
- if ( ReadSize > 0 )
- {
-
- SysBeep(1);
-
- /*
- Feedback messages use ASCII 10 (linefeed) instead of
- ASCII 13 (carriage return). Convert them and display.
- */
-
- readptr = &ReadSpace[ ReadSize - 1];
- if( *readptr == 10 ) *readptr = 13;
- *(++readptr) = '\0';
- CtoPstr(&ReadSpace);
- PostMessage( &ReadSpace, FromPrinter );
- Delay( (long int) 150, &DummyHand1);
-
- /* Update the feedback handle’s size and copy feedback. */
-
- oldsize = FHandleSize;
- FHandleSize += ReadSize;
- SetHandleSize( FeedbackHandle, FHandleSize );
-
- if( MemError() == noErr )
- {
- readptr = &ReadSpace[1];
- fbptr = (char *) *FeedbackHandle + oldsize;
- while( ReadSize-- ) *fbptr++ = *readptr++;
- };
- };
-
- /* Issue another read */
-
- if (PapRead() )
- {
- EndPCom();
- return( Failure );
- };
-
- CheckIfCancelled();
- }
- else
- {
- /* Since ReadState > 0, last read has not ended yet */
-
- DisplayStatus();
- };
-
- return( Success );
- }
-
- CloseLChannel()
- {
-
- IssueRead();
-
- /* set end-of-file */
- WriteEof = 1;
-
- /* Send empty buffer */
- WriteBuffer = "";
- WriteSize = 0;
-
- if ( PapWrite() )
- {
- EndPCom();
- return( Failure );
- };
-
- /* Wait for printer to indicate that processing is over */
-
- while ( ReadEof == 0) IssueRead();
-
- PapClose();
- PapUnload();
- DisposeWindow( PrintWinPtr );
- return( Success );
- }
-
- /*
- EndPCom:
- Closes connection immediately.
- */
-
- EndPCom()
- {
- PapClose();
- PapUnload();
- DisposeWindow( PrintWinPtr );
- sprintf( &MessageBuff, "Communication with the printer “%s” has ended.", &LaserNameBuff );
- CtoPstr( &MessageBuff );
- SimpleAlert( &MessageBuff );
- }
-
- /*
- postmessage:
- Displays messages from printer and program
- in PrintWin.
- */
-
- postmessage( s, source )
- char *s;
- int source;
- {
-
- DummyRect.left = 13;
- DummyRect.right = 335;
-
- if( source == FromProgram )
- {
- DummyRect.top = 35;
- DummyRect.bottom = 83;
- }
- else
- {
- DummyRect.top = 119;
- DummyRect.bottom = 167;
- };
-
- TextBox( &s[1], (long) s[0], &DummyRect, 0 );
-
- CheckIfCancelled();
- return( Success );
- }
-
- /*
- checkifcancelled:
- Checks if user has cancelled the
- download with Command-Period.
- */
-
- checkifcancelled()
- {
- if( GetNextEvent( everyEvent, &theEvent) == 0 )
- {
- SystemTask();
- return( Success );
- };
-
- if( theEvent.what == keyDown &&
- theEvent.modifiers & cmdKey &&
- (theEvent.message & charCodeMask ) == '.' )
- {
- EndPCom();
- return( Failure );
- };
- }
-
- /*
- TextDownload:
- Downloads the specified file to the printer
- */
-
- TextDownload( FFileName, Vnum )
- Str255 *FFileName;
- int Vnum;
- {
- long ItemsRead;
- long FileSize, Remaining;
- Str255 WorkingMessage;
-
- OpenLChannel();
-
- FErr = FSOpen( FFileName, Vnum, &FileRef );
- PtoCstr( FFileName );
-
- if ( FErr != noErr )
- {
- CloseLChannel();
- sprintf( &MessageBuff, "Sorry, the file “%s” could not be opened. Error: %d", FFileName, FErr );
- CtoPstr( &MessageBuff );
- SimpleAlert( &MessageBuff );
- return( Failure );
- };
-
- GetEOF( FileRef, &FileSize );
- Remaining = FileSize;
-
- while( Remaining )
- {
- sprintf( &WorkingMessage, "Downloading “%s”\rComplete: %ld%%", FFileName, 100 - ((Remaining * 100 )/FileSize) );
- CtoPstr( &WorkingMessage );
- PostMessage( &WorkingMessage, FromProgram );
-
- ItemsRead = 4096;
-
- FErr = FSRead( FileRef, &ItemsRead, &VirtualPage);
-
- if ( ItemsRead == 0 && FErr != eofErr )
- {
- CloseLChannel();
- goto ErrorExit;
- }
- else if ( FErr == eofErr )
- {
- WriteSize = (int) ItemsRead;
- if( sendtoprinter( VirtualPage, (int) ItemsRead ) Fails ) goto ErrorExit;
- FSClose( FileRef );
- sprintf( &MessageBuff, "“%s” has been downloaded.", FFileName, FileRef );
- CtoPstr( &MessageBuff );
- PostMessage( &MessageBuff, FromProgram );
- CloseLChannel();
- return( Success );
- };
-
- if( sendtoprinter( VirtualPage, (int) ItemsRead ) Fails ) goto ErrorExit;
- Remaining -= ItemsRead;
- };
-
- ErrorExit:
-
- FSClose( FileRef );
- sprintf( &MessageBuff, "Sorry, the file “%s” could not be downloaded.", FFileName );
- CtoPstr( &MessageBuff );
- SimpleAlert( &MessageBuff );
- return( Failure );
- }
-
- /*
- sendtoprinter:
- General downloading routine (also handles buffers > 4096 bytes)
- */
-
- sendtoprinter( bffer, bffsize )
- char *bffer;
- int bffsize;
- {
- register char *bffptr;
-
- bffptr = bffer;
-
- while( bffsize > 0)
- {
-
- if( bffsize > 4096 )
- {
- WriteSize = 4096;
- }
- else
- {
- WriteSize = bffsize;
- };
-
- WriteBuffer = bffptr;
-
- IssueRead();
-
- if ( PapWrite() )
- {
- EndPCom();
- return( Failure );
- };
-
- CheckIfCancelled();
-
- /*
- Issue reads to the printer while the
- write is processing.
- */
-
- while ( WriteState > 0 ) IssueRead();
-
- if ( WriteState < 0 )
- {
- EndPCom();
- return( Failure );
- };
-
- bffsize -= 4096;
- bffptr += 4096;
- };
-
- return( Success );
- }
-
- /*
- NoPrinter:
- Called if communications with printer can’t be established.
- */
-
- NoPrinter()
- {
- PapUnload();
- DisposeWindow( PrintWinPtr );
- sprintf( &MessageBuff, "Sorry, the printer “%s” is not currently available.", &LaserNameBuff );
- CtoPstr( &MessageBuff );
- SimpleAlert( &MessageBuff );
- return( Failure );
- };
-
- /*
- PAP glue routines:
- The routines start with a SUB command that makes room
- for the result on the stack. Then they push the appropriate
- PAP globals (allocated above) onto the stack, and jump to the
- routine’s entry point, which is at some small offset from the
- beginning of pap. When they return from the call, they pop
- the result off the stack and put it into retval, which is returned.
- */
-
- PapOpen()
- {
- int retval;
-
- asm{
- SUBQ.L #2,A7
- PEA ConnectId
- MOVE.L LaserName,-(A7)
- MOVE.W FlowQuantum,-(A7)
- PEA LaserStatus
- PEA OpenState
- MOVE.L papaddr,A0
- JSR 0(A0)
- MOVE.W (A7)+,retval
- }
- return( retval );
- }
-
- PapRead()
- {
- int retval;
-
- asm{
- SUBQ.L #2,A7
- MOVE.W ConnectId,-(A7)
- PEA ReadSpace
- PEA ReadSize
- PEA ReadEof
- PEA ReadState
- MOVE.L papaddr,A0
- JSR 4(A0)
- MOVE.W (A7)+,retval
- }
- return( retval );
- }
-
- PapWrite()
- {
-
- int retval;
-
- asm{
- SUBQ.L #2,A7
- MOVE.W ConnectId,-(A7)
- MOVE.L WriteBuffer,-(A7)
- MOVE.W WriteSize,-(A7)
- MOVE.W WriteEof,-(A7)
- PEA WriteState
- MOVE.L papaddr,A0
- JSR 8(A0)
- MOVE.W (A7)+,retval
- }
- return( retval );
- }
-
- PapStatus()
- {
- int retval;
-
- asm{
- SUBQ.L #2,A7
- MOVE.L LaserName,-(A7)
- PEA LaserStatus
- PEA LaserNode
- MOVE.L papaddr,A0
- JSR 12(A0)
- MOVE.W (A7)+,retval
- }
- return( retval );
- }
-
- PapClose()
- {
- int retval;
-
- asm{
- SUBQ.L #2,A7
- MOVE.W ConnectId,-(A7)
- MOVE.L papaddr,A0
- JSR 16(A0)
- MOVE.W (A7)+,retval
- }
- return( retval );
- }
-
- PapUnload()
- {
- int retval;
-
- asm{
- SUBQ.L #2,A7
- MOVE.L papaddr,A0
- JSR 20(A0)
- MOVE.W (A7)+,retval
- }
- return( retval );
- }